package top.jnaw.jee.utils.auth;

import com.alibaba.fastjson.JSONObject;
import com.jfinal.core.Controller;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import top.jnaw.jee.utils.Cache;
import top.jnaw.jee.utils.Https;

/**
 * Created by neo on 17-6-1.
 */
public class UpesnAuth {

  private static final String APPID = PropKit.get("upsen_appid");
  private static final String SECRET = PropKit.get("upsen_secret");

  private static final String URL_AT_FORMMATTER = "https://openapi.upesn.com/token?appid=%s&secret=%s";
  private static final String URL_UI_FORMARTTER = "https://openapi.upesn.com/certified/userInfo/%s?access_token=%s";

  private static final String CACHE_ACCESS_TOKEN_KEY = "upesn_access_token";

  /**
   * 通过 code 获取用户信息
   *
   * @param controller 当前的控制器，用来读写会话
   * @param code 友空间提供的 code 字符串
   */
  public static JSONObject byCode(Controller controller, String code) {
    JSONObject result = new JSONObject();

    // [Neo] 1. pre-verifyCaptcha code value
    if (StrKit.isBlank(code)) {

      // [Neo] 1.1 try to get from session
      String info = controller.getSessionAttr(AuthUtil.SESSION_INFO);

      if (null == info) {
        result.put("failed", "code is blank");
      } else {
        result = JSONObject.parseObject(info);
      }

      return result;
    }

    // [Neo] 2. try get access_token from cache
    JSONObject json = null;
    String access_token = (String) Cache.get(CACHE_ACCESS_TOKEN_KEY);

    // [Neo] 3. get access_token from API
    if (null == access_token) {
      final String at_content = Https
          .get(String.format(URL_AT_FORMMATTER, APPID, SECRET));
      if (StrKit.isBlank(at_content)) {
        result.put("failed", "cannot get access_token");
        return result;
      }

      json = JSONObject.parseObject(at_content);
      if (json.containsKey("code") && 0 == json.getIntValue("code") && json
          .containsKey("data") && json.getJSONObject("data")
          .containsKey("access_token")) {
        // [Neo] 3.1 cache access_token in expires timeout
        json = json.getJSONObject("data");
        access_token = json.getString("access_token");
        Cache.setx(CACHE_ACCESS_TOKEN_KEY, access_token, json.getIntValue
            ("expiresIn"));
      } else {
        result.put("failed", json.getString("msg"));
        return result;
      }
    }

    // [Neo] 4. get user info by access_token & code
    final String userinfo = Https.get(String.format(URL_UI_FORMARTTER, code,
        access_token));
    if (StrKit.isBlank(userinfo)) {
      result.put("failed", "cannot get userinfo");
      return result;
    }

    // [Neo] 5. export json
    json = JSONObject.parseObject(userinfo);
    if (json.containsKey("code") && 0 == json.getIntValue("code") && json
        .containsKey("data") && json.getJSONObject("data").containsKey
        ("user_id")) {
      result = json.getJSONObject("data");

      // [Neo] 5.1 save into session
      controller.setSessionAttr(AuthUtil.SESSION_INFO, result.toJSONString());

    } else {
      result.put("failed", json.getString("msg"));
      return result;
    }

    return result;
  }

}
